import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { Graph } from '../core/Graph.js'
import { Simulator } from '../core/Simulator.js'
import { ShaderLoader } from '../core/ShaderLoader.js'
import { GeometryGenerator } from '../core/GeometryGenerator.js'
import { GPUPicking } from '../core/GPUPicking.js'
import { cannedGraph as sampleData } from '../data/sampleData.js'

/**
 * 网络渲染器 - 负责3D网络图的渲染和交互
 */
export default class NetworkRenderer {
  constructor(canvas) {
    this.canvas = canvas
    this.scene = null
    this.camera = null
    this.renderer = null
    this.controls = null
    
    // 图数据
    this.graph = new Graph()
    this.simulator = null
    this.gpuPicking = null
    this.shaderLoader = null
    
    // 几何体和材质
    this.nodeGeometry = null
    this.edgeGeometry = null
    this.nodeMesh = null
    this.edgeMesh = null
    
    // 状态
    this.isSimulating = false
    this.temperature = 100
    this.kValue = 100
    this.layoutMode = 'force'
    
    // 动画相关
    this.isAnimatingLayout = false
    this.animationStartTime = 0
    this.animationDuration = 2000 // 2秒动画时间
    this.currentEasingType = 'easeInOutCubic' // 当前缓动类型
    this.currentPositions = null
    this.targetPositions = null
    this.startPositions = null
    
    // 时间相关
    this.timeRange = { min: 0, max: 0 }
    this.currentTimeRange = { min: 0, max: 0 }
    
    // 交互
    this.mouse = new THREE.Vector2()
    this.raycaster = new THREE.Raycaster()
    this.selectedNode = null
    this.highlightedNodes = []
    
    // 回调函数
    this.onDataUpdate = null
    
    // 动画相关
    this.animationId = null
    this.lastTime = performance.now()
    
    this.bindEvents()
  }

  /**
   * 初始化渲染器
   */
  init() {
    this.initRenderer()
    this.initScene()
    this.initCamera()
    this.initControls()
    this.initShaders()
    
    // 开始动画循环
    this.animate()
  }

  /**
   * 初始化WebGL渲染器
   */
  initRenderer() {
    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
      alpha: true
    })
    
    this.renderer.setSize(window.innerWidth, window.innerHeight)
    this.renderer.setPixelRatio(window.devicePixelRatio)
    this.renderer.setClearColor(0x000000, 1)
    
    // 启用深度测试
    this.renderer.depthTest = true
    this.renderer.depthWrite = true
  }

  /**
   * 初始化场景
   */
  initScene() {
    this.scene = new THREE.Scene()
    
    // 添加环境光
    const ambientLight = new THREE.AmbientLight(0x404040, 0.4)
    this.scene.add(ambientLight)
    
    // 添加方向光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
    directionalLight.position.set(1, 1, 1)
    this.scene.add(directionalLight)
  }

  /**
   * 初始化相机
   */
  initCamera() {
    this.camera = new THREE.PerspectiveCamera(
      75, // 更大的视角，提供更宽广的视野
      window.innerWidth / window.innerHeight,
      1, // 更合理的近裁切面
      10000
    )
    
    // 设置初始相机位置，提供更好的视角
    this.camera.position.set(800, 600, 800)
    this.camera.lookAt(0, 0, 0)
  }

  /**
   * 初始化控制器
   */
  initControls() {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    
    // 配置OrbitControls参数 - 更平滑的体验
    this.controls.enableDamping = true // 启用阻尼，使旋转更平滑
    this.controls.dampingFactor = 0.08 // 适中的阻尼系数
    this.controls.enableZoom = true // 启用缩放
    this.controls.enableRotate = true // 启用旋转
    this.controls.enablePan = true // 启用平移
    
    // 缩放限制 - 更合理的范围
    this.controls.minDistance = 50
    this.controls.maxDistance = 3000
    
    // 缩放速度
    this.controls.zoomSpeed = 1.2
    
    // 旋转速度
    this.controls.rotateSpeed = 1.0
    
    // 平移速度
    this.controls.panSpeed = 0.8
    
    // 角度限制 - 允许完全旋转
    this.controls.maxPolarAngle = Math.PI
    this.controls.minPolarAngle = 0
    
    // 目标设置为原点
    this.controls.target.set(0, 0, 0)
    
    // 自动旋转（默认关闭）
    this.controls.autoRotate = false
    this.controls.autoRotateSpeed = 1.0
    
    // 键盘控制
    this.controls.enableKeys = true
    this.controls.keys = {
      LEFT: 'ArrowLeft',
      UP: 'ArrowUp', 
      RIGHT: 'ArrowRight',
      BOTTOM: 'ArrowDown'
    }
  }


  /**
   * 初始化着色器
   */
  initShaders() {
    this.shaderLoader = new ShaderLoader()
    this.shaderLoader.onShadersLoaded = () => {
      this.onShadersReady()
    }
    this.shaderLoader.loadShaders()
  }

  /**
   * 着色器加载完成回调
   */
  onShadersReady() {
    console.log('着色器加载完成')
    // 着色器加载完成后，可以开始创建几何体
  }

  /**
   * 加载示例数据
   */
  loadSampleData() {
    try {
      // 设置图的配置
      this.graph.settings = sampleData.settings || {
        epoch: 'Event Time',
        epochFormat: 'YYYY-M-D H:m:s',
        source: 'source',
        target: 'target'
      }
      
      // 处理边数据，这会自动创建节点
      Object.values(sampleData.edges).forEach(edge => {
        edge.data.forEach(dataPoint => {
          this.graph.addEdge(dataPoint.source, dataPoint.target, dataPoint)
        })
      })
      
      // 如果有独立的节点数据，也添加它们
      if (sampleData.nodes) {
        Object.entries(sampleData.nodes).forEach(([nodeId, nodeData]) => {
          this.graph.addNode(nodeId, nodeData)
        })
      }
      
      this.processGraphData()
      this.createGeometry()
      this.initSimulator()
      
      console.log('示例数据加载完成，节点数:', this.graph.nodesCount, '边数:', this.graph.edgesCount)
    } catch (error) {
      console.error('加载示例数据失败:', error)
    }
  }

  /**
   * 处理图数据
   */
  processGraphData() {
    // 计算时间范围
    const times = []
    
    Object.values(this.graph.edges).forEach(edge => {
      edge.data.forEach(item => {
        if (item['Event Time']) {
          const time = new Date(item['Event Time']).getTime() / 1000
          times.push(time)
        }
      })
    })
    
    if (times.length > 0) {
      this.timeRange = {
        min: Math.min(...times),
        max: Math.max(...times)
      }
      this.currentTimeRange = { ...this.timeRange }
      
      if (this.onDataUpdate) {
        this.onDataUpdate({ timeRange: this.timeRange })
      }
    }
  }

  /**
   * 创建几何体
   */
  createGeometry() {
    const generator = new GeometryGenerator(this.graph)
    const { nodeGeometry, edgeGeometry } = generator.generate()
    
    this.nodeGeometry = nodeGeometry
    this.edgeGeometry = edgeGeometry
    
    // 创建材质和网格
    this.createMaterials()
    this.createMeshes()
  }

  /**
   * 创建材质
   */
  createMaterials() {
    // 节点材质
    this.nodeMaterial = new THREE.ShaderMaterial({
      vertexShader: `
        attribute vec3 color;
        varying vec3 vColor;
        void main() {
          vColor = color;
          vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
          gl_PointSize = 8.0 * (300.0 / -mvPosition.z);
          gl_Position = projectionMatrix * mvPosition;
        }
      `,
      fragmentShader: `
        varying vec3 vColor;
        void main() {
          float dist = distance(gl_PointCoord, vec2(0.5));
          if (dist > 0.5) discard;
          gl_FragColor = vec4(vColor, 1.0);
        }
      `,
      transparent: true
    })
    
    // 边材质
    this.edgeMaterial = new THREE.LineBasicMaterial({
      color: 0x666666,
      transparent: true,
      opacity: 0.6
    })
  }

  /**
   * 创建网格
   */
  createMeshes() {
    // 创建节点网格
    this.nodeMesh = new THREE.Points(this.nodeGeometry, this.nodeMaterial)
    this.scene.add(this.nodeMesh)
    
    // 创建边网格
    this.edgeMesh = new THREE.LineSegments(this.edgeGeometry, this.edgeMaterial)
    this.scene.add(this.edgeMesh)
  }

  /**
   * 初始化模拟器
   */
  initSimulator() {
    this.simulator = new Simulator(this.renderer, this.graph)
    this.simulator.init()
  }

  /**
   * 动画循环
   */
  animate() {
    this.animationId = requestAnimationFrame(() => this.animate())
    
    const currentTime = performance.now()
    const deltaTime = (currentTime - this.lastTime) / 1000
    this.lastTime = currentTime
    
    this.update(deltaTime)
    this.render()
  }

  /**
   * 更新逻辑
   */
  update(deltaTime) {
    // 更新轨道控制器
    if (this.controls) {
      this.controls.update()
    }
    
    // 处理布局动画
    if (this.isAnimatingLayout) {
      this.updateLayoutAnimation()
    }
    
    if (this.isSimulating && this.simulator && !this.isAnimatingLayout) {
      this.temperature *= 0.99
      this.simulator.update(deltaTime, this.temperature)
      
      // 更新几何体位置
      if (this.nodeGeometry && this.edgeGeometry) {
        const positions = this.simulator.getPositions()
        if (positions) {
          const geometryGenerator = new GeometryGenerator(this.graph)
          geometryGenerator.updateNodePositions(this.nodeGeometry, positions)
          geometryGenerator.updateEdgePositions(this.edgeGeometry, positions)
        }
      }
      
      if (this.onDataUpdate) {
        this.onDataUpdate({ temperature: this.temperature })
      }
    }
  }

  /**
   * 更新布局动画
   */
  updateLayoutAnimation() {
    if (!this.isAnimatingLayout || !this.startPositions || !this.targetPositions) return
    
    const currentTime = performance.now()
    const elapsed = currentTime - this.animationStartTime
    const progress = Math.min(elapsed / this.animationDuration, 1)
    
    // 使用当前选择的缓动函数
    const easedProgress = this[this.currentEasingType](progress)
    
    // 插值计算当前位置
    const positionAttribute = this.nodeGeometry.attributes.position
    
    for (let i = 0; i < positionAttribute.count * 3; i++) {
      const startPos = this.startPositions[i]
      const targetPos = this.targetPositions[i]
      const currentPos = startPos + (targetPos - startPos) * easedProgress
      
      positionAttribute.array[i] = currentPos
    }
    
    positionAttribute.needsUpdate = true
    
    // 更新边的位置
    if (this.edgeGeometry) {
      const geometryGenerator = new GeometryGenerator(this.graph)
      geometryGenerator.updateEdgePositions(this.edgeGeometry, positionAttribute.array)
    }
    
    // 动画完成
    if (progress >= 1) {
      this.isAnimatingLayout = false
      console.log('Layout animation completed')
      
      // 如果切换到力导向布局，启动模拟器
      if (this.layoutMode === 'force') {
        this.temperature = 100
        if (this.simulator) {
          this.simulator.setLayoutMode('force')
        }
      }
    }
  }

  /**
   * 渲染
   */
  render() {
    this.renderer.render(this.scene, this.camera)
  }

  /**
   * 事件绑定
   */
  bindEvents() {
    // 窗口大小改变
    window.addEventListener('resize', () => this.onWindowResize())
    
    // 鼠标事件
    this.canvas.addEventListener('click', (event) => this.onMouseClick(event))
    this.canvas.addEventListener('dblclick', (event) => this.onMouseDoubleClick(event))
  }

  /**
   * 窗口大小改变处理
   */
  onWindowResize() {
    if (this.camera && this.renderer) {
      this.camera.aspect = window.innerWidth / window.innerHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
    }
  }

  /**
   * 鼠标点击处理
   */
  onMouseClick(event) {
    // 计算鼠标位置
    this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
    
    // 射线检测
    this.raycaster.setFromCamera(this.mouse, this.camera)
    
    if (this.nodeMesh) {
      const intersects = this.raycaster.intersectObject(this.nodeMesh)
      if (intersects.length > 0) {
        this.selectNode(intersects[0].index)
      }
    }
  }

  /**
   * 鼠标双击处理
   */
  onMouseDoubleClick(event) {
    this.clearSelection()
  }

  /**
   * 选择节点
   */
  selectNode(nodeIndex) {
    this.clearSelection()
    this.selectedNode = nodeIndex
    
    // 高亮选中的节点和其邻居
    this.highlightNodeAndNeighbors(nodeIndex)
  }

  /**
   * 清除选择
   */
  clearSelection() {
    this.selectedNode = null
    this.highlightedNodes = []
    
    // 恢复所有节点颜色
    if (this.nodeGeometry && this.nodeGeometry.attributes.color) {
      const colors = this.nodeGeometry.attributes.color
      for (let i = 0; i < colors.count; i++) {
        colors.setXYZ(i, 1, 1, 1) // 白色
      }
      colors.needsUpdate = true
    }
  }

  /**
   * 高亮节点和邻居
   */
  highlightNodeAndNeighbors(nodeIndex) {
    if (!this.nodeGeometry || !this.nodeGeometry.attributes.color) return
    
    const colors = this.nodeGeometry.attributes.color
    
    // 高亮选中节点（绿色）
    colors.setXYZ(nodeIndex, 0, 1, 0)
    this.highlightedNodes.push(nodeIndex)
    
    // 找到邻居节点并高亮（蓝色）
    // 这里需要根据图结构来找邻居
    // 简化实现，随机高亮几个节点作为示例
    const neighborCount = Math.min(5, colors.count - 1)
    for (let i = 0; i < neighborCount; i++) {
      const neighborIndex = (nodeIndex + i + 1) % colors.count
      if (neighborIndex !== nodeIndex) {
        colors.setXYZ(neighborIndex, 0, 0, 1)
        this.highlightedNodes.push(neighborIndex)
      }
    }
    
    colors.needsUpdate = true
  }

  /**
   * 设置模拟状态
   */
  setSimulation(enabled) {
    this.isSimulating = enabled
  }

  /**
   * 设置K值
   */
  setKValue(value) {
    this.kValue = value
    if (this.simulator) {
      this.simulator.setKValue(value)
    }
  }

  /**
   * 重置布局
   */
  resetLayout() {
    this.temperature = 100
    if (this.simulator) {
      this.simulator.reset()
    }
  }

  /**
   * 设置布局模式
   */
  setLayoutMode(mode) {
    this.layoutMode = mode
    console.log('Setting layout mode to:', mode)
    
    // 应用新布局（带动画）
    this.animateToLayout(mode)
  }

  /**
   * 缓动函数
   */
  easeInOutCubic(t) {
    return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2
  }

  easeOutElastic(t) {
    const c4 = (2 * Math.PI) / 3
    return t === 0
      ? 0
      : t === 1
      ? 1
      : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1
  }

  easeInOutQuart(t) {
    return t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2
  }

  /**
   * 动画到新布局
   */
  animateToLayout(layoutType) {
    if (!this.nodeGeometry) return
    
    const positionAttribute = this.nodeGeometry.attributes.position
    const nodeCount = positionAttribute.count
    
    // 保存当前位置作为起始位置
    this.startPositions = new Float32Array(positionAttribute.array)
    
    // 创建目标位置数组
    this.targetPositions = new Float32Array(positionAttribute.count * 3)
    
    // 根据布局类型计算目标位置
    this.calculateTargetPositions(layoutType, this.targetPositions, nodeCount)
    
    // 开始动画
    this.isAnimatingLayout = true
    this.animationStartTime = performance.now()
    
    console.log(`Starting animation to ${layoutType} layout with ${nodeCount} nodes`)
  }

  /**
   * 计算目标位置
   */
  calculateTargetPositions(layoutType, targetPositions, nodeCount) {
    switch (layoutType) {
      case 'circle':
        this.calculateCirclePositions(targetPositions, nodeCount)
        break
      case 'sphere':
        this.calculateSpherePositions(targetPositions, nodeCount)
        break
      case 'helix':
        this.calculateHelixPositions(targetPositions, nodeCount)
        break
      case 'grid':
        this.calculateGridPositions(targetPositions, nodeCount)
        break
      case 'force':
        // 力导向布局使用随机位置，让模拟器接管
        this.calculateRandomPositions(targetPositions, nodeCount)
        break
      default:
        this.calculateRandomPositions(targetPositions, nodeCount)
        break
    }
  }

  /**
   * 计算圆形布局位置
   */
  calculateCirclePositions(positions, nodeCount) {
    const radius = 800
    
    for (let i = 0; i < nodeCount; i++) {
      const angle = (i / nodeCount) * Math.PI * 2
      
      positions[i * 3] = Math.cos(angle) * radius
      positions[i * 3 + 1] = Math.sin(angle) * radius
      positions[i * 3 + 2] = 0
    }
  }

  /**
   * 计算球形布局位置
   */
  calculateSpherePositions(positions, nodeCount) {
    const radius = 600
    
    for (let i = 0; i < nodeCount; i++) {
      // 使用斐波那契球面分布
      const y = 1 - (i / (nodeCount - 1)) * 2  // y从1到-1
      const radiusAtY = Math.sqrt(1 - y * y)
      
      const theta = (Math.PI * (3 - Math.sqrt(5))) * i  // 黄金角
      
      const x = Math.cos(theta) * radiusAtY
      const z = Math.sin(theta) * radiusAtY
      
      positions[i * 3] = x * radius
      positions[i * 3 + 1] = y * radius
      positions[i * 3 + 2] = z * radius
    }
  }

  /**
   * 计算螺旋布局位置
   */
  calculateHelixPositions(positions, nodeCount) {
    const maxRadius = 800
    const height = 1000
    
    for (let i = 0; i < nodeCount; i++) {
      const t = i / nodeCount
      const angle = t * Math.PI * 12 // 12圈螺旋
      const radius = (1 - t) * maxRadius // 螺旋向内收缩
      const y = (t - 0.5) * height
      
      positions[i * 3] = Math.cos(angle) * radius
      positions[i * 3 + 1] = y
      positions[i * 3 + 2] = Math.sin(angle) * radius
    }
  }

  /**
   * 计算网格布局位置
   */
  calculateGridPositions(positions, nodeCount) {
    const gridSize = Math.ceil(Math.cbrt(nodeCount)) // 3D网格边长
    const spacing = 120
    
    for (let i = 0; i < nodeCount; i++) {
      const x = i % gridSize
      const y = Math.floor(i / gridSize) % gridSize
      const z = Math.floor(i / (gridSize * gridSize))
      
      positions[i * 3] = (x - gridSize / 2) * spacing
      positions[i * 3 + 1] = (y - gridSize / 2) * spacing
      positions[i * 3 + 2] = (z - gridSize / 2) * spacing
    }
  }

  /**
   * 计算随机布局位置
   */
  calculateRandomPositions(positions, nodeCount) {
    const range = 1000
    
    for (let i = 0; i < nodeCount; i++) {
      positions[i * 3] = (Math.random() - 0.5) * range
      positions[i * 3 + 1] = (Math.random() - 0.5) * range
      positions[i * 3 + 2] = (Math.random() - 0.5) * range
    }
  }

  /**
   * 设置时间范围
   */
  setTimeRange(min, max) {
    this.currentTimeRange = { min, max }
    if (this.simulator) {
      this.simulator.setTimeRange(min, max)
    }
  }

  /**
   * 设置动画持续时间
   */
  setAnimationDuration(duration) {
    this.animationDuration = duration
    console.log('Animation duration set to:', duration, 'ms')
  }

  /**
   * 设置缓动类型
   */
  setEasingType(easingType) {
    this.currentEasingType = easingType
    console.log('Easing type set to:', easingType)
  }

  /**
   * 设置自动旋转
   */
  setAutoRotate(enabled, speed = 1.0) {
    if (this.controls) {
      this.controls.autoRotate = enabled
      this.controls.autoRotateSpeed = speed
      console.log('Auto rotate:', enabled ? `enabled (speed: ${speed})` : 'disabled')
    }
  }

  /**
   * 重置相机位置
   */
  resetCamera() {
    if (this.camera && this.controls) {
      this.camera.position.set(800, 600, 800)
      this.controls.target.set(0, 0, 0)
      this.controls.update()
      console.log('Camera reset to default position')
    }
  }

  /**
   * 销毁资源
   */
  dispose() {
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
    }
    
    if (this.controls) {
      this.controls.dispose()
    }
    
    if (this.renderer) {
      this.renderer.dispose()
    }
    
    if (this.nodeGeometry) {
      this.nodeGeometry.dispose()
    }
    
    if (this.edgeGeometry) {
      this.edgeGeometry.dispose()
    }
    
    window.removeEventListener('resize', this.onWindowResize)
  }
}
